// Inheritable Classes
//
// Added: 12/13/2008
// Author: John Resig
//
// Allows creation of inheritable classes.  Only downside is not
// having private members and functions. 

/* Example of usage
var Person = Object.subClass({  
  init: function(isDancing){  
    this.dancing = isDancing;  
  },  
  dance: function(){  
    return this.dancing;  
  }  
});  
 
var Ninja = Person.subClass({  
  init: function(){  
    this._super( false );  
  },  
  dance: function(){  
    // Call the inherited version of dance()  
    return this._super();  
  },  
  swingSword: function(){  
    return true;  
  }  
});  
 
var p = new Person(true);  
assert( p.dance(), "Method returns the internal true value." );  
 
var n = new Ninja();  
assert( n.swingSword(), "Get true, as we expect." );  
assert( !n.dance(), "The inverse of the super method's value - false." );  
 
// Should all be true  
assert( p instanceof Person && n instanceof Ninja && n instanceof Person,  
  "The objects inherit functionality from the correct sources." );  
*/

// Inspired by base2 and Prototype  
(function(){  
  var initializing = false,  
    // Determine if functions can be serialized  
    fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;  
 
  // Create a new Class that inherits from this class  
  Object.subClass = function(prop) {  
    var _super = this.prototype;  
 
    // Instantiate a base class (but only create the instance,  
    // don't run the init constructor)  
    initializing = true;  
    var proto = new this();  
    initializing = false;  
 
    // Copy the properties over onto the new prototype  
    for (var name in prop) {  
      // Check if we're overwriting an existing function  
      proto[name] = typeof prop[name] == "function" &&  
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?  
        (function(name, fn){  
          return function() {  
            var tmp = this._super;  
 
            // Add a new ._super() method that is the same method  
            // but on the super-class  
            this._super = _super[name];  
 
            // The method only need to be bound temporarily, so we  
            // remove it when we're done executing  
            var ret = fn.apply(this, arguments);  
            this._super = tmp;
            return ret;  
          };  
        })(name, prop[name]) :  
        prop[name];  
    }  

    // The dummy class constructor  
    function Class() {  
      // All construction is actually done in the init method  
      if ( !initializing && this.init )  
        this.init.apply(this, arguments);  
    }  

    // Populate our constructed prototype object  
    Class.prototype = proto;  

    // Enforce the constructor to be what we expect  
    Class.constructor = Class;  

    // And make this class extendable  
    Class.subClass = arguments.callee;  

    return Class;  
  };  
})();